#!/usr/bin/python3
# -*- coding: utf8 -*-
# Date   : 2021/07/20
# Author : Kwan
# Email  : allenxian@live.com
# Blog   : https://my.oschina.net/u/4173440

from queue import Queue
from threading import Thread
from time import sleep
from project.modules import DeviceGate, DeviceCamera, CarParkPlace, RecordParking, DeviceLED168, CarParkSetting
from project.define import app_logger
from .device import GateService, CameraService, LEDService, CameraQ, EntranceQ, ExitQ, TriggerQ
from .lane import Lane

"""
测试服务
"""

class Service:
    CameraSocketQ = Queue()
    LaneSocketQ = Queue()
    PlaceSocketQ = Queue()
    # 起杆队列
    UpBarQ = Queue()
    # 显示屏队列
    LEDQ = Queue()

    def __init__(self, Debug=True) -> None:
        # 设备
        self.Cameras = []
        self.Gates = []
        self.LEDs = []
        # 车位
        self.CarParkPlaces = []
        # 车道
        self.EntranceLane = Lane("Entrance")
        self.ExitLane = Lane("Exit")
        self.Debug = Debug

    def debug_switch(self):
        """
        演示开关
        """
        if self.Debug:
            self.Debug = False
        else:
            self.Debug = True
        for g in self.Gates:
            g.Debug = self.Debug

    def service_start(self):
        """
        服务初始化
        """
        try:
            self.__lanes_init()
            self.__places_init()
            self.__gates_init()
            self.__cameras_init()
            self.__leds_init()
            self.__threads_init()
            # 相机
            for c in self.Cameras:
                c.service_init()
            # 闸机
            for g in self.Gates:
                g.service_init()
        except Exception as e:
            app_logger.error(f"服务初始化失败：{e}")

    def __threads_init(self):
        """
        线程初始化
        """
        gate_event_t = Thread(target=self.__gate_trigger_task)
        camera_even_t = Thread(target=self.__camera_event_task)
        entrance_even_t = Thread(target=self.__entrance_event_task)
        exit_even_t = Thread(target=self.__exit_event_task)
        led_even_t = Thread(target=self.__led_message_task)
        upbar_t = Thread(target=self.__upbar_task)
        for t in (gate_event_t, camera_even_t, entrance_even_t, exit_even_t, led_even_t, upbar_t):
            t.setDaemon(True)
            t.start()

    def __places_modify(self, **kwargs):
        """
        车位修改
        """
        place_id = kwargs.get('PlaceID')
        gate_type = kwargs.get('GateType')
        for p in self.CarParkPlaces:
            if place_id == p['PlaceID']:
                parking = p['Parking']
                provide = p['Provide']
                valid = p['ValidCount']
                if gate_type == "Entrance":
                    parking += 1
                elif gate_type == "Exit":
                    parking -= 1
                valid = provide - parking
                p['ValidCount'] = valid
                p['Parking'] = parking
                app_logger.debug(f"车位变化：{gate_type} => {p['VehicleType']}, {p['ParkingType']} 总数：{provide} 在场：{parking} 剩余：{valid}")
                self.PlaceSocketQ.put(p)
                break

    def __upbar_task(self):
        """
        起杆事件队列
        """
        msg = dict.fromkeys(("ServerName","VehicleType","LicensePlate"))
        q = self.UpBarQ
        while True:
            if not q.empty():
                data = q.get()
                data['ServerName'] = "CarParkService"
                gate_id = data.get('GateID')
                if gate_id:
                    for g in self.Gates:
                        if gate_id == g.GateID:
                            for k, v in data.items():
                                if k in msg:
                                    msg[k] = v
                            app_logger.debug(f"发送起杆 {data.get('GateName')} => {msg}")
                            g.gate_upbar_event(**msg)
                lp = data.get("LicensePlate")
                if lp:
                    # 只有车牌起杆才修改车位
                    self.__places_modify(**data)
            sleep(0.2)

    def __led_message_task(self):
        """
        LED屏消息
        """
        msg = dict.fromkeys(("LicensePlate","VehicleType","GateMessage","GateTemp"))
        q = self.LEDQ
        while True:
            if not q.empty():
                data = q.get()
                for l in self.LEDs:
                    if l.GateID == data['GateID']:
                        for k, v in data.items():
                            if k in msg:
                                msg[k] = v
                        app_logger.debug(f"发送显示屏 {data.get('GateName')} => {msg}")
                        l.send_message(**data)
            sleep(0.2)

    def __exit_event_task(self):
        """
        出口事件
        """
        q = ExitQ
        while True:
            if not q.empty():
                data = q.get()
                data['CarParkPlaces'] = self.CarParkPlaces.copy()
                ret = self.ExitLane.lane_event(**data)
                self.LEDQ.put(ret)
                if self.ExitLane.Past:
                    self.UpBarQ.put(ret)
                self.LaneSocketQ.put(ret)
            sleep(0.2)

    def __entrance_event_task(self):
        """
        入口事件
        """
        q = EntranceQ
        while True:
            if not q.empty():
                data = q.get()
                data['CarParkPlaces'] = self.CarParkPlaces.copy()
                ret = self.EntranceLane.lane_event(**data)
                self.LEDQ.put(ret)
                if self.EntranceLane.Past:
                    self.UpBarQ.put(ret)
                self.LaneSocketQ.put(ret)
            sleep(0.2)

    def __camera_event_task(self):
        """
        相机识别事件
        """
        q = CameraQ
        while True:
            if not q.empty():
                data = q.get()
                gate_id = data.get("GateID")
                for g in self.Gates:
                    if g.GateID == gate_id:
                        g.licenseplate_result_trigger(**data)
                self.CameraSocketQ.put(data)
            sleep(0.2)

    def __gate_trigger_task(self):
        """
        闸机车辆事件
        """
        q = TriggerQ
        while True:
            if not q.empty():
                data = q.get()
                gate_id = data.get('GateID')
                vehicle_type = data.get('VehicleType')
                for c in self.Cameras:
                    if c.GateID == gate_id and c.VehicleType == vehicle_type:
                        c.licenseplate_image_trigger()
            sleep(0.2)
                    
    def __leds_init(self):
        """
        5.显示屏初始化
        """
        if len(self.Gates) > 0:
            leds = DeviceLED168.query.all()
            if leds:
                self.LEDs = [LEDService(**i.to_dict()) for i in leds]
                app_logger.debug(f"显示屏初始化完成")
            else:
                app_logger.error(f"显示屏初始化失败！")
        else:
            app_logger.error(f"请先设置闸机")

    def __cameras_init(self):
        """
        4.相机初始化
        """
        if len(self.Gates) > 0:
            cameras = DeviceCamera.query.all()
            if cameras:
                cameras = [i.to_dict() for i in cameras] 
                # 绑定相机
                for c in cameras:
                    for g in self.Gates:
                        if c['GateID'] == g.GateID:
                            c['GateType'] = g.GateType
                self.Cameras = [CameraService(**i) for i in cameras]
                app_logger.debug(f"相机初始化完成")
            else:
                app_logger.error(f"相机初始化失败！")
        else:
            app_logger.error(f"请先设置闸机")

    def __gates_init(self):
        """
        3.闸机初始化
        """
        gates = DeviceGate.query.all()
        if gates:
            self.Gates = [GateService(**i.to_dict()) for i in gates]
            for g in self.Gates:
                g.Debug = self.Debug
            app_logger.debug(f"闸机初始化完成")
        else:
            app_logger.error(f"闸机初始化失败！")

    def __places_init(self):
        """
        2.初始化车位
        """
        places = CarParkPlace.query.all()
        if places:
            self.CarParkPlaces = [i.to_dict() for i in places]
            for p in self.CarParkPlaces:
                vehicle_type = p.get('VehicleType')
                parking_type = p.get('ParkingType')
                parking = RecordParking.query.filter_by(VehicleType=vehicle_type,ParkingType=parking_type,ExitTime=None,Deleted=False).count()
                p['Parking'] = parking
                p['ValidCount'] = p['Provide'] - parking
            app_logger.debug(f"车位初始化完成：{self.CarParkPlaces}")
        else:
            app_logger.error(f"车位初始化失败！")

    def __lanes_init(self):
        """
        1.初始化车道
        """
        settings = CarParkSetting.query.first()
        settings_dict = settings.to_dict()
        self.EntranceLane.refresh_carpark_setting(**settings_dict)
        self.ExitLane.refresh_carpark_setting(**settings_dict)
        app_logger.debug(f"车道初始化完成")
    